using BrainTechLLC;
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Threading;
using System.Diagnostics;
using System.Collections;

using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Net.Sockets;



namespace Mud.EmlenMudMain
{

    /// <summary>
    /// StaticHelpers are functions that are useful, thread-safe, and
    /// can be called from pretty much anywhere
    /// </summary>
    public static class StaticHelpers
    {
        /// <summary>
        /// Determines if a string is empty... or also if it is another string
        /// For instance, "follow" may make you stop following your current
        /// leader, whereas follow self will do the same.  You can pass in 
        /// "self" here and it will return that the string is empty.
        /// </summary>
        /// <param name="sz"></param>
        /// <param name="szAlsoConsiderEmpty"></param>
        /// <returns></returns>
        public static bool Empty(string sz, string szAlsoConsiderEmpty)
        {
            if (string.IsNullOrEmpty(sz)) return true;
            else if (sz == szAlsoConsiderEmpty) return true;
            else return false;
        }
        
        /// <summary>
        /// If you expect leading or trailing spaces involved, you can
        /// trim them off before checking if the string is empty
        /// </summary>
        /// <param name="sz"></param>
        /// <param name="fTrim"></param>
        /// <returns></returns>
        public static bool Empty(string sz, bool fTrim)
        {
            if (string.IsNullOrEmpty(sz)) return true;
            else if (fTrim == true) return string.IsNullOrEmpty(sz.Trim());
            else return false;
        }
        /// <summary>
        /// Converts "Yes" "No" "On" "Off" "True" "False" into boolean values
        /// for easy interpretation.  Note: Nah = No, since we only check
        /// the first character
        /// </summary>
        /// <param name="sz"></param>
        /// <param name="fDefault"></param>
        /// <returns></returns>
        public static bool YesNoOnOffTrueFalse(string sz, bool fDefault)
        {
            if (!StaticHelpers.Empty(sz, true))
            {
                switch (char.ToUpper(sz[0]))
                {
                    case 'Y': return true;
                    case 'T': return true;
                    case 'N': return false;
                    case 'F': return false;
                    case 'O':
                        {
                            if (sz.Length > 1)
                            {
                                if (char.ToUpper(sz[1]) == 'N') return true;
                                if (char.ToUpper(sz[1]) == 'F') return false;
                            }
                        }
                        break;
                }
            }
            return fDefault;
        }

        /// <summary>
        /// Given a boolean, returns "on" or "off"
        /// </summary>
        /// <param name="f"></param>
        /// <returns></returns>
        public static string GetOnOrOff(bool f) { return (f) ? "on" : "off"; }
        /// <summary>
        /// Given a boolean, returns yes or no
        /// </summary>
        /// <param name="f"></param>
        /// <returns></returns>
        public static string GetYesOrNo(bool f) { return (f) ? "yes" : "no"; }
        /// <summary>
        /// Given a boolean, returns true or false
        /// </summary>
        /// <param name="f"></param>
        /// <returns></returns>
        public static string GetTrueOrFalse(bool f) { return (f) ? "true" : "false"; }

        /// <summary>
        /// Get the relationship between YOU and the direction.. i.e.
        /// "arrives from"... "above/below/the west/etc"
        /// </summary>
        /// <param name="dir"></param>
        /// <returns></returns>
        public static string GetDirectionMessage(GeneralDirection dir)
        {
            switch (dir)
            {
                // TODO HEREHERE
                //case GeneralDirection.down:
                //  return "below";
                //case GeneralDirection.up:
                //  return "above";
                default:
                    return "the " + dir.ToString();
            }
        }

        /// <summary>
        /// Builds a hash code based on the first two letters of a string
        /// </summary>
        /// <param name="sz"></param>
        /// <returns></returns>
        public static int FirstTwoLettersHash(string sz)
        {
            if (sz == null) return 0;
            if (sz.Length < 1) return 0;
            int n = (int)char.ToUpper(sz[0]);
            if (sz.Length < 2) return n;
            n = (n * 256) + (int)char.ToUpper(sz[1]);
            return n;
        }

        /// <summary>
        /// Makes HTML safe with the Web Interface and uses HtmlEncode
        /// to ensure nobody inserts nasty scripts
        /// </summary>
        /// <param name="sz"></param>
        /// <returns></returns>
        public static string MakeHTMLSafe(string sz)
        {
            string szCopy = sz;
            szCopy = szCopy.Replace('|', ':');
            //szCopy = System.Web.HttpUtility.HtmlEncode(szCopy);
            return szCopy;
        }

        /// <summary>
        /// Capitalizes the first letter of a string
        /// </summary>
        /// <param name="sz"></param>
        /// <returns></returns>
        public static string FirstLetterCap(string sz)
        {
            if (sz == null) return "";
            if (sz == "") return "";
            string szNew = char.ToUpper(sz[0]).ToString() + sz.Substring(1);
            return szNew;
        }


        /// <summary>
        /// Takes a number and converts it to a ordered string... for instance:
        /// 1st, 2nd, 3rd, 4th, 5th, ... 44th..
        /// </summary>
        /// <param name="n"></param>
        /// <returns></returns>
        public static string NumberToOrderString(int n)
        {
            int nDiv10 = n / 10;
            string sNum = nDiv10.ToString();
            int nMod10 = n - (nDiv10 * 10);
            switch (nMod10)
            {
                case 1: return sNum + "1st";
                case 2: return sNum + "2nd";
                case 3: return sNum + "3rd";
                default:
                    return n.ToString() + "th";
            }
        }

        /// <summary>
        /// Adds an HTML table cell with the specified text to an HTML table row
        /// </summary>
        /// <param name="row"></param>
        /// <param name="szText"></param>
        /// <returns></returns>
        //public static HtmlTableCell AddCell(HtmlTableRow row, string szText)
        //{
        //  HtmlTableCell cell = new HtmlTableCell();
        //  cell.InnerHtml = szText + " ";
        //  row.Cells.Add(cell);
        //  return cell;
        //}

        /// <summary>
        /// Returns the REVERSE direction of dir.  For instance:
        /// ReverseDirectionOf(GeneralDirection.East) returns GeneralDirection.W
        /// </summary>
        /// <param name="dir"></param>
        /// <returns></returns>
        public static GeneralDirection ReverseDirectionOf(GeneralDirection dir)
        {
            return dir.ReverseDirection();
            //ReverseDirections revdir = (ReverseDirections)((int)dir);
            //GeneralDirection newdir = (GeneralDirection)(Enum.Parse(typeof(GeneralDirection), revdir.ToString()));
            //return newdir;
        }

        /// <summary>
        /// Returns a direction letter (like N E S W, etc)
        /// </summary>
        /// <param name="dir"></param>
        /// <returns></returns>
        public static string DirFirstLetterCap(GeneralDirection dir)
        {
#if NO_SILVERLIGHT
            string sz = Enum.Format(typeof(GeneralDirection), dir, "G");
#else 
            string sz = dir.ToString();
#endif

            return sz.Substring(0, 1).ToUpper();
        }



        /// <summary>
        /// l = level
        /// i = char's intelligence
        /// w = char's wisdom
        /// a = random from 1-10
        /// b = random from 10-20
        /// c = random from 20-30
        /// d = random from 1-level
        /// m = Syntax m42 would be max of 42 damage (numeric only)
        /// z = Syntax z3 would be minimum 3 damage (numeric only)
        /// k = kick damage
        /// g = Wizard's Guild then 1, else 0
        /// h = Healer's Guild then 1, else 0
        /// o = Warrior's Guild then 1, else 0
        /// t = max HPCurrent points... used for mob experience calc.
        /// please note: all operations are performed from left to right. This makes
        /// for simple coding, and a damn quick pass thru a complicated expression.
        /// sample:
        /// l+w/3 would be written in real terms as: l/3 + w/3 or (l+w)/3
        /// i+w+l*2/3+l would be written in real terms as: (((i+w)+l)*2)/3)+l
        /// You can now use parens :)     
        /// </summary>
        /// <param name="szLine">The "equation" string to be calculated</param>
        /// <param name="level">level to be used for the l varaible</param>
        /// <param name="chr">The character to be used for calculations</param>
        /// <returns></returns>
        public static long translate(string szLine, int level, CharacterData chr)
        {
            long dam = 0;
            long cur_num = 0;
            char cur_op = '+';
            if (szLine == null) return 0;
            if (szLine == "") return 0;

            for (int pos = 0; pos < szLine.Length; pos++)
            {
                char c = szLine[pos];

                if (char.IsNumber(c) == true)
                {
                    cur_num *= 10;
                    cur_num += (long)(int)((c - '0'));
                }
                else if (c == ')')
                {
                    if (cur_op == '*')
                        dam *= cur_num;
                    if (cur_op == '/')
                        dam /= cur_num;
                    if (cur_op == '+')
                        dam += cur_num;
                    if (cur_op == '-')
                        dam -= cur_num;
                    return dam;
                }
                else if (c == '(')
                {
                    StringBuilder sb = new StringBuilder(16);
                    pos++;
                    if (pos >= szLine.Length) return dam;
                    c = szLine[pos];
                    while (c != ')')
                    {
                        sb.Append(c);
                        pos++;
                        if (pos >= szLine.Length) return dam;
                        c = szLine[pos];
                    }
                    pos++;
                    if (pos >= szLine.Length) return dam;
                    cur_num = translate(sb.ToString(), level, chr);
                }
                else if (c == 't')
                {
                    cur_num = chr.HPMax;
                }
                else if (c == 'g')
                {
                    cur_num = (chr.pcdata == null) ? 0 :
                      (((chr.pcdata.Guilds & GuildType.Wizard) != 0) ? 1 : 0);
                }
                else if (c == 'h')
                {
                    cur_num = (chr.pcdata == null) ? 0 :
                      (((chr.pcdata.Guilds & GuildType.Healer) != 0) ? 1 : 0);
                }
                else if (c == 'o')
                {
                    cur_num = (chr.pcdata == null) ? 0 :
                      (((chr.pcdata.Guilds & GuildType.Warrior) != 0) ? 1 : 0);
                }
                else if (c == 'z')
                {
                    if (cur_op == '*')
                        dam *= cur_num;
                    else if (cur_op == '/')
                        dam /= cur_num;
                    else if (cur_op == '+')
                        dam += cur_num;
                    else if (cur_op == '-')
                        dam -= cur_num;
                    else dam = cur_num;
                    cur_op = '[';
                    cur_num = 0;
                    pos++;
                    if (pos >= szLine.Length) return dam;
                    long tnn = 0;
                    while (pos < szLine.Length && Char.IsNumber(szLine[pos]) == true)
                    {
                        c = szLine[pos];
                        tnn *= 10;
                        tnn += (long)(int)((c - '0'));
                        pos++;
                    }
                    if (dam < tnn)
                    {
                        dam = tnn;
                        cur_num = tnn;
                    }
                    if (pos >= szLine.Length) return dam;
                    pos--;
                    continue;
                }
                else if (c == 'm')
                {
                    if (cur_op == '*')
                        dam *= cur_num;
                    else if (cur_op == '/')
                        dam /= cur_num;
                    else if (cur_op == '+')
                        dam += cur_num;
                    else if (cur_op == '-')
                        dam -= cur_num;
                    else dam = cur_num;
                    cur_op = '[';
                    cur_num = 0;
                    pos++;
                    if (pos >= szLine.Length) return dam;
                    long tnn = 0;
                    while (pos < szLine.Length && Char.IsNumber(szLine[pos]))
                    {
                        c = szLine[pos];
                        tnn *= 10;
                        tnn += (long)(int)((c - '0'));
                        pos++;
                    }
                    if (dam > tnn)
                    {
                        dam = tnn;
                        cur_num = tnn;
                    }
                    if (pos >= szLine.Length) return dam;
                    pos--;
                    continue;
                }
                else if (c == '+')
                {
                    if (cur_op == '*')
                        dam *= cur_num;
                    else if (cur_op == '/')
                        dam /= cur_num;
                    else if (cur_op == '+')
                        dam += cur_num;
                    else if (cur_op == '-')
                        dam -= cur_num;
                    else dam = cur_num;
                    cur_op = '+';
                    cur_num = 0;
                }
                else if (c == '-')
                {
                    if (cur_op == '*')
                        dam *= cur_num;
                    else if (cur_op == '/')
                        dam /= cur_num;
                    else if (cur_op == '+')
                        dam += cur_num;
                    else if (cur_op == '-')
                        dam -= cur_num;
                    else dam = cur_num;
                    cur_op = '-';
                    cur_num = 0;
                }
                else if (c == '/')
                {
                    if (cur_op == '*')
                        dam *= cur_num;
                    else if (cur_op == '/')
                        dam /= cur_num;
                    else if (cur_op == '+')
                        dam += cur_num;
                    else if (cur_op == '-')
                        dam -= cur_num;
                    else dam = cur_num;
                    cur_op = '/';
                    cur_num = 0;
                }
                else if (c == '*')
                {
                    if (cur_op == '*')
                        dam *= cur_num;
                    else if (cur_op == '/')
                        dam /= cur_num;
                    else if (cur_op == '+')
                        dam += cur_num;
                    else if (cur_op == '-')
                        dam -= cur_num;
                    else dam = cur_num;
                    cur_op = '*';
                    cur_num = 0;
                }
                else if (c == 'd')
                    cur_num = Rand.RandIntBetween(1, level);
                else if (c == 'k')
                    cur_num = (chr.pcdata == null) ? 0 : chr.pcdata.Plus_kick;
                else if (c == 'l')
                    cur_num = level;
                else if (c == 'w')
                    cur_num = (chr.pcdata == null) ? 0 : ((IStats)chr.pcdata.TemporaryStats1)[StatTypes.Wisdom];
                else if (c == 'i')
                    cur_num = (chr.pcdata == null) ? 0 : ((IStats)chr.pcdata.TemporaryStats1)[StatTypes.Intelligence];
                else if (c == 's')
                    cur_num = (chr.pcdata == null) ? 0 : ((IStats)chr.pcdata.TemporaryStats1)[StatTypes.Strength];
                else if (c == 'x')
                    cur_num = (chr.pcdata == null) ? 0 : ((IStats)chr.pcdata.TemporaryStats1)[StatTypes.Constitution];
                else if (c == 'y')
                    cur_num = (chr.pcdata == null) ? 0 : ((IStats)chr.pcdata.TemporaryStats1)[StatTypes.Dexterity];
                else if (c == 'a')
                    cur_num = Rand.RandIntBetween(1, 10);
                else if (c == 'b')
                    cur_num = Rand.RandIntBetween(10, 20);
                else if (c == 'c')
                    cur_num = Rand.RandIntBetween(20, 30);
            }

            if (cur_op == '*')
                dam *= cur_num;
            else if (cur_op == '/')
                dam /= cur_num;
            else if (cur_op == '+')
                dam += cur_num;
            else if (cur_op == '-')
                dam -= cur_num;
            else dam = cur_num;
            return dam;
        }
    }
}